/*
   Copyright (c) [Year] [name of copyright holder]
   [Software Name] is licensed under Mulan PSL v2.
   You can use this software according to the terms and conditions of the Mulan PSL v2. 
   You may obtain a copy of Mulan PSL v2 at:
            http://license.coscl.org.cn/MulanPSL2 
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
   See the Mulan PSL v2 for more details.  
*/

#ifndef JIAJIA_JJCOMPILER_HPP
#define JIAJIA_JJCOMPILER_HPP

#include"jiajiastd.hpp"
#include"lmccreducestack.hpp"
#include"jjsrc.hpp"
#include"jjenv.hpp"
#include"jjsymtab.hpp"
#include"jjir.hpp"
#include"lmccparser.hpp"

namespace jiajia{

    class jjcompiler{
    private:
        my::ufile mFile;
        my::ubuffer mBuf;
        my::unicode_t mLastU;
        jjtoken mToken;

        jjenv mEnv;
        jjsymtab mTab;
        jjir mIR;

        jjexe mEXE;

    public:
        jjcompiler():
            mBuf(),
            mToken(),
            mEnv(),
            mTab(),
            mIR(),
            mEXE()
            {}

        void open(const std::string & filename){
            mFile.open(filename);
        }

        // 向前一个 unicode
        my::unicode_t nextUnicode(){
            mLastU = my::unicode::ToHalf(mBuf.nextUnicode(mFile));
            std::cout<<my::utf8::UnicodeToStr(mLastU);
            return mLastU;
        }

        // 回退一个 unicode
        void backUnicode(){
            if(mLastU != my::unicode::eof){
                mBuf.backUnicode();
                std::cout<<"\nback = "<<my::utf8::UnicodeToStr(mLastU)<<std::endl;
            }
        }

        word_t nextWord(){
            word_t w;
            w = lmcc::NEXTWORD(*this);
            std::cout<<"word = "<<lmcc::WORDSTR(w)<<std::endl;
            while(jjtoken::IsIgnore(w)){
                mBuf.throwOnly();
                w = lmcc::NEXTWORD(*this);
            }

            mToken.put(mBuf);
            mToken.word = w;

            if(w <= lmcc::begin_of_err){
                log.err("jiajia::jjcompiler::nextWord 发生错误了。但是我却还没有写错误处理的函数。哈哈哈。");
                w = lmcc::_empty;
            }

            return w;
        }

        // constant
        void genConstant(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            value_t * result = mTab.newTemp();
            s.topToken().parseValue(result);
            s.top().set(lmcc::_constant, result);
        }

        // factor -> _lparen expr _rparen
        void genParenFactor(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            // 弹出 _lparen
            jjtoken t = s.topToken();
            s.pop();

            // 弹出 expr
            lmcc::rsnode expr_node = s.top();
            expr_node.token += t;
            s.pop();

            // 弹出 _rparen
            expr_node.token += s.topToken();
            s.pop();

            s.push(expr_node);
        }

        // expr
        // 一些编辑，生成代码的操作
        bool genExpr(const code_t code, const word_t w){
            // 2020-3-19 为了减少临时值的创建个数，打算返回值将由后面的表达式填充
            // 比如　a = -1, $ 为 未知的意思
            // -1 将生成节点　[code::MINUS, $, 1, $]
            // 返回值部分由　a　节点填充。
            // [code::MINUS, $, 1, a]
            // 唯一的不好的地方是，如果某条语句无返回值呢？
            // 有多条语句要回填返回值呢？

            // 2020-3-19 我放弃了，还是多几个临时值好，生成简单

            lmcc::reducestack & s = lmcc::reducestack::en();
            bool flag = true;
            jjtoken t;
            jjirnode * node = mIR.insertBack(mEnv.topEnd());
            // 关于 begin
            // 1. 如果 rhs 是一个表达式，那么 begin 会被 rhs.begin 覆盖
            // 2. 如果 lhs 是一个表达式，那么 begin 会被 lhs.begin 覆盖
            jjirnode * begin = node;
            value_t * rhs = nullptr;
            value_t * lhs = nullptr;
            value_t * result = nullptr;

            switch(code){
            case code::ASSIGN:{
                // assignexpr -> lhs _assign rhs

                // rhs
                lmcc::rsnode & rhs_node = s.top();

                if(rhs_node.begin != nullptr)
                    begin = rhs_node.begin;

                rhs = rhs_node.result;
                t = s.topToken();
                s.pop();

                // 弹出 assign
                t = (s.topToken() += t);
                s.pop();

                // lhs
                lmcc::rsnode lhs_node = s.top();
                t += lhs_node.token;
                s.pop();

                if(lhs_node.word == lmcc::_idexpr){
                    begin = lhs_node.begin;
                    // 如果是 _idexpr 则要进行左值转换即，code::FIND -> code::INSERT, code::GFIND -> code::GINSERT
                    jjirnode::ToLHExpr(lhs_node.begin, lhs_node.end);
                    lhs = lhs_node.result;
                }else if(lhs_node.word == lmcc::_ta){
                    lhs = lhs_node.result;
                }else{
                    switch(lhs_node.word){
                    case lmcc::_constant: log.err("\"常量\"不能被赋值语句修改。"); break;
                    case lmcc::_shi: case lmcc::_fou: log.err("\"是否\"不能被赋值语句修改。"); break;
                    case lmcc::_loopfactor: log.err("\"循环因子\"不能被赋值语句修改。"); break;
                    default: log.err("赋值语句要求左边为左值表达式。"); break;
                    }
                    flag = false;
                }

                if(flag){
                    node->genUNARY(code::ASSIGN, rhs, lhs);
                    node->setToken(t);
                }
            }
                break;
            case code::MINUS:{
                // _sub rhs

                // rhs
                lmcc::rsnode & rhs_node = s.top();
                if(rhs_node.begin != nullptr)
                    begin = rhs_node.begin;

                rhs = rhs_node.result;
                t = s.topToken();
                s.pop();

                // 弹出 _sub
                t = (s.topToken() += t);
                s.pop();

                result = mTab.newTemp();
                node->genUNARY(code::MINUS, rhs, result);
                node->setToken(t);
            }
                break;
            case code::ADD:
            case code::SUB:
            case code::MULT:
            case code::DEV:
            case code::LINK:
            case code::EQ:
            case code::NE:
            case code::GT:
            case code::LT:
            case code::GE:
            case code::LE:{
                // lhs code::XXX rhs

                // 弹出右边的值
                lmcc::rsnode & rhs_node = s.topExpr();
                rhs = rhs_node.result;
                if(rhs_node.begin != nullptr) begin = rhs_node.begin;
                t = s.topToken();
                std::cout<<rhs_node.token.getLog()<<", "<<rhs_node.result<<", "<<rhs<<std::endl;
                s.pop();

                // 弹出运算符
                t = (s.topToken() += t);
                s.pop();

                // 弹出左边的值
                lmcc::rsnode & lhs_node = s.topExpr();
                lhs = lhs_node.result;
                if(lhs_node.begin != nullptr) begin = lhs_node.begin;
                t += s.topToken();
                s.pop();

                result = mTab.newTemp();
                node->genEXPR(code, lhs, rhs, result);
                node->setToken(t);
            }
                break;
            default: break;
            }
            mEnv.toRHS();

            if(flag)
                s.pushExpr(w, t, begin, node, result);
            else{
                log.endl().err(std::move(t.getLog()));
                s.pushWord(lmcc::_err);
            }
            return flag;
        }

        // 逻辑运算
        inline void genAND(const word_t word){
            genLogic(code::IFFALSE, word);
        }

        inline void genOR(const word_t word){
            genLogic(code::IFTRUE, word);
        }

        void genLogic(const code_t code, const word_t word){
            lmcc::reducestack & s = lmcc::reducestack::en();
            jjtoken t;
            jjirnode * if_node = nullptr;
            jjirnode * node1 = nullptr;
            jjirnode * node2 = nullptr;
            jjirnode * begin = nullptr;
            jjirnode * end = mIR.insertBack(mEnv.topEnd());
            end->genGOTONEXT();

            value_t * result = mTab.newTemp();
            // lhs && rhs 的逻辑如下
            // 如果 lhs == true, 返回 rhs
            // 如果 lhs == false, 返回 lhs
            // 所以转换成 IR 如下
            // 0. TOBOOL lhs result
            // 1. IFFALSE result m
            //  ...
            // n. TOBOOl rhs result
            // m. ...

            // lhs || rhs 的逻辑如下
            // 如果 lhs == true, 返回 lhs
            // 如果 lhs == false, 返回 rhs
            // 所以转换成 IR 如下
            // 0. TOBOOL lhs result
            // 1. IFTRUE result n
            //  ...
            // n. TOBOOL rhs result
            // m. ...

            // 弹出右边的值
            lmcc::rsnode rhs_node = s.top();
            value_t * rhs = rhs_node.result;
            t = rhs_node.token;
            s.pop();

            // 弹出 && ，||
            t = (s.topToken() += t);
            s.pop();

            lmcc::rsnode lhs_node = s.top();
            value_t * lhs = lhs_node.result;
            t += lhs_node.token;
            s.pop();

            // 1. 首先 lhs 必须要在 rhs 前面运算。
            // 2. 因为有可能 lhs 为常量或其他只有值的 rsnode ，所以有可能会造成 rhs 永远先比 lhs 作出运算
            // 3. 也有可能两个都是只有值，那就可以随意添加，没有运算先后

            // 4. 两个都是只有值的生成时，按循序生成
            // node1    :   [TOBOOL, lhs, result]
            // if_node  :   [IFXXX, result, n]
            // node2    :   [TOBOOL, rhs, result]
            // n        :   ...

            // 5. 当 lhs 为只有值时，
            // 把 node1 生成在 rhs_node.begin 前
            // 把 if_node 生成在 rhs_node.begin 前
            // 把 node2 生成在 rhs_node.end 后
            // node1            :   [TOBOOL, lhs, result]
            // if_node          :   [IFXXX, result, n]
            // rhs_node.begin   :   ...
            // rhs_node.end     :   ...
            // node2            :   [TOBOOL, rhs, result]
            // n                :   ...

            // 6. 当 rhs 为只有值时，
            // 把 node1 生成在 lhs_node.end 后
            // 把 if_node 生成在 node1 后
            // 把 node2 生成在 if_node 后
            // lhs_node.begin   :   ...
            // lhs_node.end     :   ...
            // node1            :   [TOBOOL, lhs, result]
            // if_node          :   [IFXXX, result, n]
            // node2            :   [TOBOOL, rhs, result]
            // n                :   ...

            // 7. 当 lhs 和 rhs 都有值时
            // 把 node1 生成在 rhs_node.begin 前
            // 把 node2 生成在 rhs_node.begin 前
            // 把 if_node 生成在 rhs_node.begin 前
            // lhs_node.begin   :   ...
            // lhs_node.end     :   ...
            // node1            :   [TOBOOL, lhs, result]
            // if_node          :   [IFXXX, result, n]
            // rhs_node.begin   :   ...
            // rhs_node.end     :   ...
            // node2            :   [TOBOOL, rhs, result]
            // n                :   ...

            jjir & ir = mIR;
            if(rhs_node.begin == nullptr){
                begin = (lhs_node.begin != nullptr)? lhs_node.begin:node1;
            }else{
                begin = node1;
            }

            node1 = ir.insertBack(lhs_node.begin == nullptr? end:rhs_node.begin);
            node1->genUNARY(code::TOBOOL, lhs, result);
            node1->setToken(lhs_node.token);

            if_node = ir.insertBack(lhs_node.begin == nullptr? end:rhs_node.begin);
            if_node->genIF(code, result, end);

            node2 = ir.insertBack(end);
            node2->genUNARY(code::TOBOOL, rhs, result);
            node2->setToken(rhs_node.token);

            s.pushExpr(word, t, begin, node2, result);
        }
        // ## 编译器的一些内定的全局变量 begin ##
        // factor -> _shi
        void genShi(){
            lmcc::reducestack::en().top().set(lmcc::_shi, mTab.shi());
        }

        // factor -> _fou
        void genFou(){
            lmcc::reducestack::en().top().set(lmcc::_fou, mTab.fou());
        }

        // factor -> _loopfactor
        bool genLoopFactor(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            jjenvnode & e = mEnv.findLOOP();
            // 找到循环语句
            if(e.mode == jjenvnode::LOOP_MODE){
                value_t * factor = e.value(jjenvnode::LOOP_FACTOR);
                s.top().set(lmcc::_loopfactor, factor);
            }else{
                // 没有进入循环，循环因子，使用错误报错
                log.err("还不能使用\"循环因子\"语句，请检查\"直到...\"语句后面是否遗漏了\"结束\"语句。")
                    .endl()
                    .err(s.topToken().getLog());
                return false;
            }
            mEnv.toRHS();
            return true;
        }
        // ## 编译器的一些内定的全局变量 end ##

        // _id
        void genID(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            jjtoken & t = s.topToken();
            string_t * name = mTab.insertID(t);
            value_t * table_val = nullptr;

            value_t * result = mTab.newTemp();
            jjirnode * node = mIR.insertBack(mEnv.topEnd());

            jjenvnode & e = mEnv.findSEQ();
            if(e.mode == jjenvnode::INIT_MODE){
                table_val = mEnv.mainValue();
            }else{
                table_val = e.value(jjenvnode::SEQ_TA);
            }

            // 如果没有主值，或进入了右值生成节奏则使用全局变量查找
            if(table_val == nullptr || !mEnv.lhsFlag()){
                node->genGLOBAL(code::GFIND, name, result);
                node->setToken(t);
            }else{
                node->genTABLE(code::FIND, table_val, name, result);
                node->setToken(t);
            }

            s.top().set(lmcc::_idexpr, node, node, result);
        }

        // _ta
        bool genTA(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            value_t * main_val = nullptr;
            jjenvnode & e = mEnv.findSEQ();
            if(e.mode == jjenvnode::INIT_MODE){
                main_val = mEnv.mainValue();
                if(main_val == nullptr){
                    // 没有主值的报错
                    log.err("找不到主值，请先定义一个主值。").endl().err(std::move(s.topToken().getLog()));
                    return false;
                }
            }else{
                main_val = e.value(jjenvnode::SEQ_TA);
            }
            s.top().set(lmcc::_ta, main_val);
            return true;
        }

        // idexpr -> idexpr _de _id
        void genIDEXPR(){
            lmcc::reducestack & s = lmcc::reducestack::en();

            value_t * val = nullptr;
            value_t * result = nullptr;

            jjirnode * node = mIR.insertBack(mEnv.topEnd());
            jjirnode * begin = node;

            // 抛出 _id
            string_t * name = mTab.insertID(s.topToken());
            jjtoken t = s.topToken();
            s.pop();

            // 抛出 ‘的’
            t = (s.topToken() += t);
            s.pop();

            // 弹出 idexpr
            val = s.topResult();
            if(s.topWord() == lmcc::_ta){
                result = mTab.newTemp();
            }else{
                begin = s.top().begin;
                result = val;
            }
            t += s.topToken();
            s.pop();

            node->genTABLE(code::FIND, val, name, result);
            node->setToken(t);

            s.pushExpr(lmcc::_idexpr, t, begin, node, result);
        }

        // idexpr -> idexpr _lbracket expr _rbracket
        void genIDATEXPR(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            
            value_t * lhs = nullptr;
            value_t * rhs = nullptr;
            value_t * result = nullptr;

            jjirnode * node = mIR.insertBack(mEnv.topEnd());
            jjirnode * begin = node;

            // 弹出 _rbracket
            jjtoken t = s.topToken();
            s.pop();

            // 弹出 expr
            lmcc::rsnode & expr_node = s.top();
            rhs = expr_node.result;
            if(expr_node.begin != nullptr) begin = expr_node.begin;
            t += s.topToken();
            s.pop();

            // 弹出 _lbracket
            t += s.topToken();
            s.pop();

            // 弹出 _idexpr
            lhs = s.topResult();
            if(s.topWord() == lmcc::_ta){
                result = mTab.newTemp();
            }else{
                begin = s.top().begin;
                result = lhs;
            }
            t += s.topToken();
            s.pop();

            node->genEXPR(code::AT, lhs, rhs, result);
            node->setToken(t);

            s.pushExpr(lmcc::_idexpr, t, begin, node, result);
        }

        // ## stmt begin ##
        // shifoustmt -> expr
        bool genExprStmt(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            bool flag = true;
            lmcc::rsnode expr_node = s.top();
            s.pop();

            jjirnode * ir = nullptr;
            enum_t mode = mEnv.topMode();
            if(mode == jjenvnode::CALL_MODE){
                ir = mIR.insertBack(mEnv.topEnd());
                ir->genARGPUSH(expr_node.result);
                ir->setToken(expr_node.token);
            }else if(mode == jjenvnode::UNITIL_MODE){
                log.err("请检查前面的\"直到...\"语句后面是否遗漏了\"结束\"语句。")
                    .endl()
                    .err(std::move(expr_node.token.getLog()));
                flag = false;
            }else{
                jjenvnode & e = mEnv.findSEQ();
                switch(expr_node.word){
                case lmcc::_idexpr:
                    if(e.mode == jjenvnode::INIT_MODE && mEnv.mainValue() == nullptr){
                        jjirnode::ToLHExpr(expr_node.begin, expr_node.end);
                        mEnv.setMainValue(expr_node.result);
                    }
                    break;
                default: break;
                }
            }

            s.pushWord(lmcc::_stmt);
            return flag;
        }

        // shifoustmt -> expr w expr
        bool genShiFouStmt(code_t code){
            lmcc::reducestack & s = lmcc::reducestack::en();
            // rhs_expr
            value_t * rhs = s.topResult();
            jjtoken t = s.topToken();
            s.pop();

            // lmcc::shifouXX
            t = (s.topToken() += t);
            s.pop();

            // lhs_expr
            value_t * lhs = s.topResult();
            t += s.topToken();
            s.pop();

            bool flag = true;
            // 检查环境
            enum_t mode = mEnv.topMode();
            if(mode == jjenvnode::CALL_MODE){
                log.err("函数调用参数中不能使用\"是否...\"语句。");
                flag = false;
            }else if(mode == jjenvnode::UNITIL_MODE){
                log.err("请检查前面的\"直到...\"语句后面是否遗漏了\"结束\"语句。");
                flag = false;
            }

            if(flag){
                jjirnode * node = mIR.insertBack(mEnv.topEnd());
                node->genEXPR(code, lhs, rhs, mTab.shi());
                node->setToken(t);

                node = mIR.insertBack(mEnv.topEnd());
                node->genUNARY(code::NO, mTab.shi(), mTab.fou());
                node->setToken(t);
            }else{
                log.endl().err(std::move(t.getLog()));
            }

            s.pushWord(lmcc::_stmt);
            return flag;
        }

        // stmt -> _if expr
        bool genIF(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            bool flag = true;
            value_t * result = nullptr;

            // 弹出 expr
            jjtoken t = s.topToken();
            result = s.topResult();
            s.pop();

            // 弹出 _if
            t = (s.topToken() += t);
            s.pop();

            enum_t mode = mEnv.topMode();
            if(mode == jjenvnode::UNITIL_MODE){
                log.err("还不能使用\"如果...\"语句，请检查\"直到...\"语句后面是否遗漏了\"结束\"语句。");
                flag = false;
            }else if(mode == jjenvnode::CALL_MODE){
                // 进入函数调用阶段
                log.err("函数调用参数中不能使用\"如果...\"语句。");
                flag = false;
            }

            if(flag){
                mEnv.enterIF(t, mIR, result);
            }else{
                log.endl().err(std::move(t.getLog()));
            }

            s.pushWord(lmcc::_stmt);
            return flag;
        }

        // stmt -> _elif expr
        bool genELIF(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            bool flag = true;
            // 弹出 expr
            jjirnode * expr_begin = s.top().begin;
            value_t * result = s.top().result;
            jjtoken t = s.topToken();
            s.pop();

            // 弹出 _elif
            t = (s.topToken() += t);
            s.pop();

            enum_t mode = mEnv.topMode();
            if(mode != jjenvnode::IF_MODE && mode != jjenvnode::ELIF_MODE){
                if(mode == jjenvnode::LOOP_MODE){
                    log.err("\"循环...\"语句中不能使用\"但如果...\"或\"但是如果...\"语句。");
                }if(mode == jjenvnode::UNITIL_MODE){
                    log.err("还不能使用\"但如果...\"或\"但是如果...\"语句，请检查\"直到...\"语句后面是否遗漏了\"结束\"语句。");
                }else if(mode == jjenvnode::ELSE_MODE){
                    log.err("\"否则...\"语句后面不能使用\"但如果...\"或\"但是如果...\"语句。");
                }else if(mode == jjenvnode::CALL_MODE){
                    log.err("函数调用参数中不能使用\"但如果...\"或\"但是如果...\"语句。");
                }else{
                    log.err("请在\"如果...\"语句中使用\"但如果...\"或\"但是如果...\"语句。");
                }

                flag = false;
            }

            if(flag)
                mEnv.enterELIF(t, mIR, expr_begin, result);
            else
                log.endl().err(std::move(t.getLog()));

            s.pushWord(lmcc::_stmt);
            return flag;
        }

        // stmt -> _else
        bool genELSE(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            bool flag = true;
            jjtoken t = s.topToken();
            s.pop();

            enum_t mode = mEnv.topMode();
            if(mode != jjenvnode::IF_MODE && mode != jjenvnode::ELIF_MODE){
                if(mode == jjenvnode::LOOP_MODE){
                    log.err("不能在\"循环...\"语句中使用\"否则...\"语句。");
                }else if(mode == jjenvnode::ELSE_MODE){
                    log.err("不能在\"否则...\"语句中使用\"否则...\"语句。");
                }else if(mode == jjenvnode::CALL_MODE){
                    log.err("不能在函数调用中使用\"否则...\"语句。");
                }else{
                    std::cout<<"mode == "<<(int)mode<<std::endl;
                    log.err("请在\"如果...\"或\"但如果...\"或\"但是如果...\"语句中使用\"否则...\"语句。");
                }

                flag = false;
            }

            if(flag)
                mEnv.enterELSE(mIR);
            else{
                log.endl().err(std::move(t.getLog()));
            }

            s.pushWord(lmcc::_stmt);
            return flag;
        }

        // stmt -> _loop
        bool genLoop(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            bool flag = true;
            jjtoken t = s.topToken();
            s.pop();

            enum_t mode = mEnv.topMode();
            if(mode == jjenvnode::UNITIL_MODE){
                log.err("还不能使用\"循环...\"语句，请检查\"直到...\"语句后面是否遗漏了\"结束\"语句。");
                flag = false;
            }else if(mode == jjenvnode::CALL_MODE){
                log.err("函数调用参数中不能使用\"循环...\"语句。");
                flag = false;
            }

            if(flag){
                mEnv.enterLOOP(t, mTab, mIR);
            }else{
                log.endl().err(std::move(t.getLog()));
            }

            s.pushWord(lmcc::_stmt);
            return flag;
        }

        // stmt -> _until expr
        bool genUntil(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            bool flag = true;
            // 弹出 expr
            value_t * result = s.topResult();
            jjtoken t = s.topToken();
            s.pop();

            // 弹出 _until
            t = (s.topToken() += t);
            s.pop();

            enum_t mode = mEnv.topMode();
            if(mode != jjenvnode::LOOP_MODE){
                if(mode == jjenvnode::UNITIL_MODE){
                    log.err("还不能使用\"直到...\"语句，请检查\"直到...\"语句后面是否遗漏了\"结束\"语句。");
                }else if(mode == jjenvnode::CALL_MODE){
                    log.err("函数调用参数中不能使用\"直到...\"语句。");
                }else{
                    log.err("请在\"循环...\"语句中使用\"直到...\"语句。");
                }
                flag = false;
            }

            if(flag)
                mEnv.enterUNTIL(t, result);
            else
                log.endl().err(std::move(t.getLog()));

            s.pushWord(lmcc::_stmt);
            return flag;
        }

        // 循环停止语句
        // stmt -> _break
        bool genBreak(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            bool flag = true;
            jjtoken t = s.topToken();
            s.pop();

            enum_t mode = mEnv.topMode();
            if(mode == jjenvnode::UNITIL_MODE){
                log.err("还不能使用\"循环结束\"语句，请检查\"直到...\"语句后面是否遗漏了\"结束\"语句。");
                flag = false;
            }else if(mode == jjenvnode::CALL_MODE){
                log.err("函数调用参数中不能使用\"循环结束\"语句。");
                flag = false;
            }else{
                jjenvnode & e = mEnv.findLOOP();
                if(e.mode == jjenvnode::LOOP_MODE){
                    jjirnode * node = mIR.insertBack(mEnv.topEnd());
                    node->genGOTO(e.node(jjenvnode::LOOP_BREAK));
                    node->setToken(t);
                }else{
                    // 没有进入循环但使用，循环停止，的报错
                    log.err("找不到\"循环...\"语句，请在\"循环...\"语句中使用\"循环停止\"语句。");
                    flag = false;
                }
            }

            if(!flag){
                log.endl().err(std::move(t.getLog()));
            }

            s.pushWord(lmcc::_stmt);
            return flag;
        }

        // 循环继续语句
        // stmt -> _continue
        bool genContinue(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            bool flag = true;
            jjtoken t = s.topToken();
            s.pop();

            enum_t mode = mEnv.topMode();
            if(mode == jjenvnode::UNITIL_MODE){
                log.err("还不能使用\"循环继续\"语句，请检查\"直到...\"语句后面是否遗漏了\"结束\"语句。");
                flag = false;
            }else if(mode == jjenvnode::CALL_MODE){
                log.err("函数调用参数中不能使用\"循环继续\"语句。");
                flag = false;
            }else{
                jjenvnode & e = mEnv.findLOOP();
                if(e.mode == jjenvnode::LOOP_MODE){
                    jjirnode * node = mIR.insertBack(mEnv.topEnd());
                    node->genGOTO(e.node(jjenvnode::LOOP_FMOVE));
                    node->setToken(s.topToken());
                }else{
                    // 没有进入循环但使用，循环继续，的报错
                    log.err("找不到\"循环...\"语句，请在\"循环...\"语句中使用\"循环继续\"语句。");
                    flag = false;
                }
            }

            if(!flag){
                log.endl().err(std::move(t.getLog()));
            }

            s.pushWord(lmcc::_stmt);
            return flag;
        }

        // 结束语句
        // stmt -> _end
        bool genEnd(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            bool flag = true;
            jjtoken t = s.topToken();
            s.pop();

            enum_t mode = mEnv.topMode();
            switch(mode){
            case jjenvnode::LOOP_MODE:
            case jjenvnode::UNITIL_MODE:
            case jjenvnode::IF_MODE:
            case jjenvnode::ELIF_MODE:
            case jjenvnode::ELSE_MODE:
                mEnv.quit();
                break;
            case jjenvnode::CALL_MODE:
                log.err("函数调用参数中不能使用\"结束\"语句。");
                flag = false;
                break;
            default:
                log.err("找不到需要结束的语句，请在\"循环...\"、\"直到...\"、\"如果...\"、\"但如果...\"、\"否则...\"、等语句后使用\"结束\"语句。");
                flag = false;
                break;
            }

            if(!flag){
                log.endl().err(std::move(t.getLog()));
            }

            s.pushWord(lmcc::_stmt);
            return flag;
        }

        // stmt -> _lbrace seqbody _rbrace
        void genSeq(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            s.pop();
            s.pop();
            s.pop();

            mEnv.quit();
            s.pushWord(lmcc::_stmt);
        }

        // ## stmt end ##

        // 因为 LOOP 都在环境中保存着，所以干脆直接输入弹出多少个算了
        // void genLoop(){
        //     // 循环语句比较特殊
        //     // 默认应该是一个死循环，然后一个跳出的条件判断
        //     // 还有一个循环因子记录已经第几次循环，所以需要在循环开始之前初始化为 0
        //     // 所以循环语句的大概模样为:
        //     // 0 : [code::assgin, 0, factor]
        //     // 1 : [code::add, factor, 1, factor]
        //     // ...
        //     // n : [code::IFFALSE, cond, 1 ]
        //     // n+1 : ...

        //     // 如果忽略了直到语句，则完全为死循环，大概模样为:
        //     // 0 : [code::assgin, 0, factor]
        //     // 1 : [code::add, factor, 1, factor]
        //     // ...
        //     // n : [code::goto, 1]
        //     // n+1 : ...

        //     // 循环语句块没有返回值，谨记，使用 STMT_FLAG 记录

        //     lmcc::reducestack & s = lmcc::reducestack::en();
        //     s.pop();
        //     s.pop();

        //     s.pushStmt(lmcc::_stmt, mEnv.topBegin(), mEnv.topEnd()->mBack);
        //     mEnv.quit();
        //     mEnv.toLHS();
        // }

        // 函数
        // 生成函数头部
        bool genCallHead(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            bool flag = true;
            jjtoken t = s.topToken();
            func_t f = func.findFunc(t);
            s.pop();

            if(f == nullptr){
                // 函数找不到报错
                log.err("找不到函数\""+t.getSrc().toString()+"\"。");
                flag = false;
            }

            // 弹出 @
            t = (s.topToken() += t);
            s.pop();

            if(flag){
                mEnv.enterCALL(mTab, mIR, f);
                mEnv.toRHS();
            }else{
                log.endl().err(std::move(t.getLog()));
            }
            s.pushToken(lmcc::_callhead, t);
            return flag;
        }

        // 函数调用
        void genCall(int len){
            lmcc::reducestack & s = lmcc::reducestack::en();
            jjenvnode & e = mEnv.top();
            value_t * result = e.value(jjenvnode::CALL_RESULT);
            jjirnode * node = nullptr;

            // 弹出参数部分
            for(int i = 0; i < len; ++i)
                s.pop();

            // 弹出 函数名
            jjtoken t = s.topToken();
            s.pop();

            if(len == 0){
                // 调用主值函数
                // 以主语作为参数

                jjenvnode & e = mEnv.findSEQ();
                value_t * main_val = nullptr;

                if(e.mode == jjenvnode::INIT_MODE){
                    main_val = mEnv.mainValue();
                }else{
                    main_val = e.value(jjenvnode::SEQ_TA);
                }

                if(main_val != nullptr){
                    node = mIR.insertBack(mEnv.topEnd());
                    node->genARGPUSH(main_val);
                }
            }

            node = mIR.insertBack(mEnv.topEnd());
            node->genCALL(e.func(jjenvnode::CALL_FUNC), result);
            node->setToken(t);

            mEnv.quit();
            mEnv.toRHS();

            s.pushExpr(lmcc::_call, t, e.begin(), node, result);
        }

        // // 生成第一个参数
        // bool genArg(){
        //     lmcc::reducestack & s = lmcc::reducestack::en();
        //     jjirnode * node = mIR.insertBack(mEnv.topEnd());
        //     jjirnode * begin = node;

        //     node->genARGPUSH(s.topExpr().result);
        //     node->setToken(s.topToken());

        //     s.top().set(lmcc::_args);
        //     return true;
        // }

        // // 生成第 n 个参数
        // bool genArgs(){
        //     lmcc::reducestack & s = lmcc::reducestack::en();
        //     jjirnode * node = mIR.insertBack(mEnv.topEnd());

        //     // 弹出 expr
        //     jjtoken t = s.topToken();
        //     node->genARGPUSH(s.topExpr().result);
        //     node->setToken(t);
        //     s.pop();

        //     // 弹出 _comma
        //     t += s.topToken();
        //     s.pop();

        //     // 弹出 _args
        //     s.topToken() += t;
        //     return true;
        // }

        // // 生成参数
        // void genArgStmt(int len){
        //     lmcc::reducestack & s = lmcc::reducestack::en();

        //     // 弹出 )
        //     jjtoken t = s.topToken();
        //     s.pop();

        //     if(len == 3){
        //         t += s.topToken();
        //         s.pop();
        //     }

        //     // 弹出 (
        //     t += s.topToken();
        //     s.pop();

        //     s.pushToken(lmcc::_call, t);
        // }

        // ## 通用 begin ##
        void genWord(const word_t w, const int size){
            lmcc::reducestack & s = lmcc::reducestack::en();
            for(int i = 0; i < size; ++i)
                s.pop();
            s.pushWord(w);
        }

        void genSeqBody(const int len){
            lmcc::reducestack & s = lmcc::reducestack::en();
            for(int i = 0; i < len; ++i)
                s.pop();
            s.pushWord(lmcc::_seqbody);
        }

        void genStmts(const int len){
            lmcc::reducestack & s = lmcc::reducestack::en();
            // jjirnode * begin = nullptr;
            // jjirnode * end = nullptr;
            for(int i = 0; i < len; ++i){
                // if(end == nullptr)
                //     end = s.top().end;
                // if(s.top().begin != nullptr)
                //     begin = s.top().begin;
                s.pop();
            }

            s.pushWord(lmcc::_stmts);
        }

        // 语句块
        void genBlock(const int len){
            lmcc::reducestack & s = lmcc::reducestack::en();
            // jjirnode * begin = nullptr;
            // jjirnode * end = nullptr;
            for(int i = 0; i < len; ++i){
                // if(end == nullptr)
                //     end = s.top().end;
                // if(s.top().begin != nullptr)
                //     begin = s.top().begin;
                s.pop();
            }

            s.pushWord(lmcc::_block);
        }
        // ## 通用 end ##

        // ## 代码块 begin ##

        inline bool exe(){
            std::cout<<"\n中间件: "<<mIR<<"\n";
            std::cout<<"运行结果:\n";
            bool flag = mEXE.exe(mTab, mIR);
            std::cout<<std::endl;
            // 清空环境
            mEnv.clear();
            mTab.clearTemp();
            mIR.free();

            return flag;
        }

        bool genBlocks(int size){
            lmcc::reducestack s = lmcc::reducestack::en();
            for(int i = 0; i < size; ++i)
                s.pop();

            s.pushWord(lmcc::_blocks);

            // 直接返回执行的结果
            return this->exe();
        }
        
        // ## 代码块 end ##

        // ## shi begin ##
        // lbrace, {, 进入数组初始化操作
        bool shiLBrace(){
            lmcc::reducestack s = lmcc::reducestack::en();
            enum_t mode = mEnv.topMode();
            if(mode == jjenvnode::UNITIL_MODE){
                log.err("还不能使用\"{添加数组}\"语句，请检查\"直到...\"语句后面是否遗漏了\"结束\"语句。")
                    .endl()
                    .err(std::move(s.topToken().getLog()));
                return false;
            }else if(mode == jjenvnode::CALL_MODE){
                log.err("函数调用参数中不能使用\"{添加数组}\"语句。")
                    .endl()
                    .err(std::move(s.topToken().getLog()));
                return false;
            }

            value_t * main_val = nullptr;
            jjenvnode & e = mEnv.findSEQ();
            if(e.mode == jjenvnode::INIT_MODE){
                main_val = mEnv.mainValue();
                if(main_val == nullptr){
                    log.err("还不能使用\"{添加数组}\"语句，找不到主值，请先定义一个主值。")
                        .endl()
                        .err(std::move(s.topToken().getLog()));
                    return false;
                }
            }else{
                main_val = e.value(jjenvnode::SEQ_TA);
            }
            mEnv.enterSEQ(mTab, mIR, main_val);
            return true;
        }

        bool shiSemicolon(){

        }

        // 一些生成代码那里使用的代码
        inline bool shi(){
            lmcc::reducestack & s = lmcc::reducestack::en();
            bool flag = true;
            enum_t mode = mEnv.topMode();
            switch(mToken.word){
            case lmcc::_true:
            case lmcc::_false:
            case lmcc::_str:
            case lmcc::_realnum:
            case lmcc::_add:
            case lmcc::_sub:
            case lmcc::_mult:
            case lmcc::_dev:
            case lmcc::_assign:
            case lmcc::_lt:
            case lmcc::_gt:
            case lmcc::_le:
            case lmcc::_ge:
            case lmcc::_ne:
            case lmcc::_or:
            case lmcc::_and:
            case lmcc::_if:
            case lmcc::_elif:
            case lmcc::_until:
            case lmcc::_at:
                mEnv.toRHS();
                break;
            case lmcc::_lbrace:
                flag = shiLBrace();
                break;
            case lmcc::_rbrace: break;
            case lmcc::_dun:
                // 、
                mEnv.enterPUSH(mIR);
                mEnv.toLHS();
                break;
            case lmcc::_semicolon:
                // ；
                mEnv.clear();
                break;
            case lmcc::_comma:
                // ，
                if(mode != jjenvnode::CALL_MODE){
                    mEnv.toLHS();
                }
                break;
            default: break;
            }
            s.pushToken(mToken);
            return flag;
        }

        // ## shi end ##
        inline void lrerror(const int state){
            std::cout<<"state = "<<state<<std::endl;
            for(word_t w = lmcc::begin_of_id; w < lmcc::num_of_id; ++w){
                if(lmcc::_action_cmd[state][w] == lmcc::CMD_SHI){
                    std::cout<<"fuck"<<std::endl;
                    log.err(std::move(std::string("或者想输入的是 ") + std::string(lmcc::WORDSTR(w))))
                        .endl()
                        .err(mToken.getLog());
                    break;
                }
            }
        }

        inline bool run(){
            bool flag = lmcc::PARSER(*this);
            if(flag == false){
                log.err("文件"+mFile.filename()+"里:").errend();
            }

            return flag;
        }

        void print(std::ostream & os) const  {
            std::cout<<"mToken: "<<mToken<<"\n";
            std::cout<<"mIR: "<<mIR<<"\n";
        }
    };

    std::ostream & operator<<(std::ostream & os, const jjcompiler & compiler){
        compiler.print(os);
        return os;
    }
}

#endif
